#ifndef RAY_TRACE_PRO_BBOX_H
#define RAY_TRACE_PRO_BBOX_H

#include "VectorMath.h"

namespace RayTracePro
{
	using namespace GxLibMath;

	class BBox
	{
	public:
		union
		{
			struct
			{
				float xMin, yMin, zMin, xMax, yMax, zMax;
			};
			struct
			{
				Vec3 Min, Max;
			};
		};
		BBox()
		{}
		BBox(const BBox & b1, const BBox & b2)
		{
			*this = b1;
			Union(b2);
		}
		inline void Init()
		{
			xMin = yMin = zMin = FLT_MAX;
			xMax = yMax = zMax = -FLT_MAX;
		}
		inline void Union(const BBox & box)
		{
			xMin = GxLibMath::Min(box.xMin, xMin);
			yMin = GxLibMath::Min(box.yMin, yMin);
			zMin = GxLibMath::Min(box.zMin, zMin);

			xMax = GxLibMath::Max(box.xMax, xMax);
			yMax = GxLibMath::Max(box.yMax, yMax);
			zMax = GxLibMath::Max(box.zMax, zMax);
		}
		inline void Union(const Vec3 &v)
		{
			xMin = GxLibMath::Min(v.x, xMin);
			yMin = GxLibMath::Min(v.y, yMin);
			zMin = GxLibMath::Min(v.z, zMin);

			xMax = GxLibMath::Max(v.x, xMax);
			yMax = GxLibMath::Max(v.y, yMax);
			zMax = GxLibMath::Max(v.z, zMax);
		}
	};

	inline void TransformBBox(BBox & bboxOut, const Matrix4 & mat, const BBox & bboxIn)
	{
		Vec3 v, v_t;
		bboxOut.Init();
		for (int i = 0; i < 8; i++)
		{
			if (i & 1)
				v.x = bboxIn.xMax;
			else
				v.x = bboxIn.xMin;
			if (i & 2)
				v.y = bboxIn.yMax;
			else
				v.y = bboxIn.yMin;
			if (i & 4)
				v.z = bboxIn.zMax;
			else
				v.z = bboxIn.zMin;
			mat.Transform(v_t, v);
			bboxOut.Union(v_t);
		}
	}
}

#endif